package it.pgp.sevenzipjbindingandroidexample;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import net.sf.sevenzipjbinding.ArchiveFormat;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.IInStream;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class MainActivity extends Activity {

    private static final String TAG = "Version";

    public static void testExtract(File file, File destDir, boolean testOnly, ArchiveFormat format) {
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
            RandomAccessFileInStream inStream = new RandomAccessFileInStream(randomAccessFile);
            ArchiveOpenCallback callback = new ArchiveOpenCallback();
            IInArchive inArchive = SevenZip.openInArchive(format, inStream, callback);
//            IInArchive inArchive = SevenZip.openInArchive(format, inStream, "123456");
            ArchiveExtractCallback extractCallback = new ArchiveExtractCallback(inArchive, destDir, testOnly);
            inArchive.extract(null, testOnly, extractCallback);

            inArchive.close();
            inStream.close();
            Log.i(TAG, "Extract OK");
        } catch (FileNotFoundException e) {
            Log.e(TAG, e.getMessage());
        } catch (SevenZipException e) {
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
    }

    public static void testExtractRarMultiVolume(File firstVolumePath, File destDir, boolean isTestMode) {

        ArchiveOpenVolumeCallback archiveOpenVolumeCallback = null;
        IInArchive inArchive = null;
        try {

            archiveOpenVolumeCallback = new ArchiveOpenVolumeCallback();
            IInStream inStream = archiveOpenVolumeCallback.getStream(firstVolumePath.getAbsolutePath());
            inArchive = SevenZip.openInArchive(ArchiveFormat.RAR5, inStream, //
                    archiveOpenVolumeCallback);

            System.out.println("   Size   | Compr.Sz. | Filename");
            System.out.println("----------+-----------+---------");
            int itemCount = inArchive.getNumberOfItems();
            for (int i = 0; i < itemCount; i++) {
                System.out.println(String.format("%9s | %9s | %s", //
                        inArchive.getProperty(i, PropID.SIZE), //
                        inArchive.getProperty(i, PropID.PACKED_SIZE), //
                        inArchive.getProperty(i, PropID.PATH)));
            }

            // extract/test archive
            ArchiveExtractCallback extractCallback = new ArchiveExtractCallback(inArchive, destDir, isTestMode);
            inArchive.extract(null, isTestMode, extractCallback);
            Log.i("MultiVolume", "Extract/Test OK");
        } catch (Exception e) {
            System.err.println("Error occurs: " + e);
        } finally {
            if (inArchive != null) {
                try {
                    inArchive.close();
                } catch (SevenZipException e) {
                    System.err.println("Error closing archive: " + e);
                }
            }
            if (archiveOpenVolumeCallback != null) {
                try {
                    archiveOpenVolumeCallback.close();
                } catch (IOException e) {
                    System.err.println("Error closing file: " + e);
                }
            }
        }
    }

    private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 1;

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授权了权限，可以进行操作
            } else {
                // 用户拒绝了权限，可以引导用户手动开启
                openWriteExternalStorageSettings();
            }
        }
    }

    private void openWriteExternalStorageSettings() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SevenZip.Version version = SevenZip.getSevenZipVersion();
        Log.i(TAG, "7-zip version: " + version.major + "." + version.minor + "." + version.build + " (" + version.version + "), " + version.date + version.copyright);
        Log.i(TAG, "7-Zip-JBinding version: " + SevenZip.getSevenZipJBindingVersion());
        Log.i(TAG, "Native library initialized: " + SevenZip.isInitializedSuccessfully());

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            // 未授权，请求权限
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_WRITE_EXTERNAL_STORAGE);
        } else {
            // 已授权，可以进行操作
        }

        File srcFile = new File("/storage/emulated/0/rars/123.7z");
//        File srcFile = new File("/storage/emulated/0/rars/simple.7z");
        File destDir = new File("/storage/emulated/0/rars/extracted123");
//        File destDir = new File("/storage/emulated/0/rars/7zsimple1");
        ArchiveFormat format = ArchiveFormat.RAR5;
//        ArchiveFormat format = ArchiveFormat.SEVEN_ZIP;
        destDir.mkdirs();

        new Thread(()->testExtract(
                srcFile,
                destDir,
                false,
                null
        )).start();

        File srcArchiveMultiVolume = new File("/storage/emulated/0/rars/1234.rar");
        File destDirMultiVolume = new File("/storage/emulated/0/rars/multipartExtracted");
        destDirMultiVolume.mkdirs();

        new Thread(()->testExtractRarMultiVolume(
                srcArchiveMultiVolume,
                destDirMultiVolume,
                true)).start();
    }
}